-- 和其外界交互层

local resty_http = require('modules.mission.resty.http')
local mis_uu = require('modules.commhm.utils')
local ns_network = require('modules.commhm.network')
local log       = require("modules.commhm.log");
local ngx = ngx
local pairs = pairs
local type = type
local tostring = tostring
local string_match = string.match
local math_floor = math.floor
local math_random = math.random
local table_insert = table.insert
local ngx_encode_args = ngx.encode_args

local mis_config = nil
local mis_common = nil
local mis_log = nil
local mis_saveAss = nil
local t_retCode = nil

--------------------------------------------------------------
local mis_bridge = {
	s_name = string.match(debug.getinfo(1).short_src, '.*/(.*).lua');	-- 模块名称
}
local this = mis_bridge

--------------------------------------------------------------
-- 说明：模块包含
-- 参数：模块表
this.modules_include = function(t_moddules)
	mis_config = t_moddules.mis_config
	mis_common = t_moddules.mis_common
	mis_log = t_moddules.mis_log
	mis_saveAss = t_moddules.mis_saveAss
	t_retCode = mis_config.t_retCode
end

--------------------------------------------------------------
-- 说明：响应工具函数，格式化数据然后发送
-- 参数：n_code			状态码
--		ts_msg			附带数据
--		n_responseType	数据格式
this.send = function(n_code, ts_msg, n_responseType)
	mis_uu.var_dump({ret = n_code or t_retCode.n_SYS_ERR, msg = ts_msg})
	if n_responseType == 1 then
		ngx.say(mis_common.table_to_json({ret = n_code or t_retCode.n_SYS_ERR, msg = ts_msg}))
	else
		ngx.say(mis_common.table_to_string({ret = n_code or t_retCode.n_SYS_ERR, msg = ts_msg}))
	end
end

local function http_post( url, request, data, headers, timeout )
    timeout = timeout or 3000
    headers = headers or {}
    headers["Connection"]     = "Keep-Alive"
    headers["User-Agent"]     = "mnw"

    local url_str = ngx_encode_args(request)
    local uri = not url_str and url or url .. '?' .. url_str
    local code, body = ns_network.postHttpPage( uri, data, timeout, headers )
    mis_uu.var_dump({ uri = uri, body = data, result = { code = code, body = body } })

    if code == 200 then
        return (body or '')
    end

    mis_log.error(mis_uu.to_str({ uri = uri, result = { code = code, body = body } }))
    return nil
end

--------------------------------------------------------------
-- 说明：发起http/https请求
-- 参数：s_name				请求名
--		s_url				请求链接
-- 		s_method			请求方法
--		t_header			请求头
--		t_body				请求体
--		b_ignoreRemoteErr	忽略远程错误
-- 返回：n					状态码
--		s 					描述
local function http_request(s_name, s_url, s_method, t_header, t_body, b_ignoreRemoteErr)
	local t_http, t_res
	local s_err
	local n_logLevel = ngx.ctx.n_logLevel
	if not ngx.ctx.t_http then
		t_http, s_err = resty_http:new()
		if not t_http then
			mis_log.error(s_err)
			return t_retCode.n_NET_ERR, s_err
		end
		t_http:set_timeout(mis_config.n_httpReqTimeOut)
		ngx.ctx.t_http = t_http
	end

	if n_logLevel and n_logLevel > 0 then
		mis_log.debug(s_url)
	end

	local t_pack = {
		ssl_verify = false;
		method = s_method;
		headers = t_header;
		body = t_body;
		keepalive_timeout = mis_config.n_httpKeepaliveTimeOut;
		keepalive_pool = mis_config.n_httpPoolSize;
	}
	t_res, s_err = ngx.ctx.t_http:request_uri(s_url, t_pack)

	if not t_res then
		mis_log.error(s_err)
		return t_retCode.n_NET_ERR, s_err
	elseif t_res.status ~= 200 and t_res.status ~= 201 and not b_ignoreRemoteErr then
		s_err = s_name .. ' failed, status:' .. t_res.status
		mis_log.error(s_err)
		return t_retCode.n_NET_ERR, s_err
	else
		if n_logLevel and n_logLevel > 0 then
			mis_log.debug('-----------------------------------------')
			mis_log.debug(s_name)
			mis_log.debug('status:' .. t_res.status)
			if n_logLevel == 2 then
				mis_log.debug('----------------')
				mis_log.debug(mis_common.table_to_json(t_pack))
				mis_log.debug('----------------')
				mis_log.debug('headers:')
				for s_k, s_v in pairs(t_res.headers) do
					mis_log.debug(s_k .. '=' .. s_v)
				end
				mis_log.debug('body:')
				mis_log.debug(t_res.body)
			end
		end
		return t_retCode.n_OK, t_res.body
	end
end

--------------------------------------------------------------
-- 说明：查询物品是否存在
-- 参数：n_uin 				迷你号
--		s_items				道具列表json串
-- 返回：n					状态码
--		ts 					描述
this.check_item_exist = function(n_uin, s_items)
	local s_base = mis_config.t_accountAddr.t_base[n_uin % #mis_config.t_accountAddr.t_base + 1]
	local s_cmd = 'any'
	local n_ts = ngx.time()
	local s_sign = ngx.md5(s_cmd .. s_items .. n_ts .. n_uin .. '522e6ccde68f4584a3282ce0b0eca1cf')
	local s_url = s_base .. mis_config.t_accountAddr.s_exist .. 'cmd=' .. s_cmd .. '&ts=' .. n_ts ..
		'&uin=' .. n_uin .. '&items=' .. s_items .. '&sign=' .. s_sign
	local n_code, ts_desc = http_request('check_item_exist', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		return n_code, ts_desc
	end
	ts_desc = mis_common.json_to_table(ts_desc)
	if ts_desc.return_code == 'SUCCESS' and ts_desc.return_result then
		return n_code, ts_desc.return_result
	else
		mis_log.error('check item exist failed, ' .. (ts_desc.return_msg or '') .. ', ' .. s_url)
		return t_retCode.n_SYS_ERR, 'check item exist failed'
	end
end

--------------------------------------------------------------
-- 说明：请求账号服扣费
-- 参数：n_uin				迷你号
-- 		n_itemId 			道具Id
--		n_num 				数量
--		n_type 				货币类型
-- 		s_reason			描述
--		s_exdata			附带数据
-- 返回：n					状态码
--		ts 					描述(返回账号服的状态码)
this.cost_money = function(n_uin, n_itemId, n_num, n_type, s_reason, s_exdata)
	if n_type == mis_config.t_costType.n_COIN then
		local s_base = mis_config.t_accountAddr.t_base[n_uin % #mis_config.t_accountAddr.t_base + 1]
		local s_sign = ngx.md5(s_exdata .. s_reason .. n_num .. n_uin .. '522e6ccde68f4584a3282ce0b0eca1cf')
		local s_url = s_base .. mis_config.t_accountAddr.s_coin .. '&exdata=' .. s_exdata ..
			'&reason=' .. s_reason .. '&rmnum=' .. n_num .. '&uin=' .. n_uin .. '&sign=' .. s_sign
		local n_code, s_desc = http_request('cost_money', s_url, 'GET')
		if n_code ~= t_retCode.n_OK then
			return n_code, s_desc
		end
		local t_desc = mis_common.json_to_table(s_desc)
		if t_desc.code == 'SUCCESS' then
			return t_retCode.n_OK
		else
			mis_log.error('cost coin failed, ' .. s_desc .. ', ' .. s_url)
			return t_desc.errorcode or t_retCode.n_SYS_ERR, 'cost coin failed'
		end
	elseif n_type == mis_config.t_costType.n_BEAN then
		local s_prefix = mis_config.t_accountAddr.t_gm[n_uin % #mis_config.t_accountAddr.t_gm + 1]
		local s_cmd = 'minibean_rm'
		local n_ts = ngx.time()
		local s_sign = ngx.md5(s_cmd .. s_exdata .. n_num .. s_reason .. n_ts .. n_uin .. '522e6ccde68f4584a3282ce0b0eca1cf')
		local s_url = s_prefix .. 'cmd=' .. s_cmd .. '&exdata=' .. s_exdata .. '&minibean=' .. n_num ..
			'&reason=' .. s_reason .. '&ts=' .. n_ts .. '&uin=' .. n_uin .. '&sign=' .. s_sign
		local n_code, s_desc = http_request('cost_money', s_url, 'GET')
		if n_code ~= t_retCode.n_OK then
			return n_code, s_desc
		end
		local t_desc = mis_common.json_to_table(s_desc)
		if t_desc.return_code == 'SUCCESS' then
			return t_retCode.n_OK
		else
			mis_log.error('cost bean failed, '.. s_desc .. ', ' .. s_url)
			return t_desc.errorcode or t_retCode.n_SYS_ERR, 'cost bean failed'
		end
	elseif n_type == mis_config.t_costType.n_ITEM then
		local s_prefix = mis_config.t_accountAddr.t_gm[n_uin % #mis_config.t_accountAddr.t_gm + 1]
		local s_cmd = 'item_rm'
		local n_ts = ngx.time()
		local s_sign = ngx.md5(s_cmd .. s_exdata .. n_itemId .. n_num .. s_reason .. n_ts .. n_uin .. '522e6ccde68f4584a3282ce0b0eca1cf')
		local s_url = s_prefix .. 'cmd=' .. s_cmd .. '&exdata=' .. s_exdata .. '&id=' .. n_itemId ..
			'&num=' .. n_num .. '&reason=' .. s_reason .. '&ts=' .. n_ts .. '&uin=' .. n_uin .. '&sign=' .. s_sign
		local n_code, s_desc = http_request('cost_money', s_url, 'GET')
		if n_code ~= t_retCode.n_OK then
			return n_code, s_desc
		end
		local t_desc = mis_common.json_to_table(s_desc)
		if t_desc.return_code == 'SUCCESS' then
			return t_retCode.n_OK
		else
			mis_log.error('cost item failed, ' .. s_desc .. ', ' .. s_url)
			return t_desc.errorcode or t_retCode.n_SYS_ERR, 'cost item failed'
		end
	end
end

--------------------------------------------------------------
-- 说明：请求账号服加道具
-- 参数：n_uin 				迷你号
--		t_items				道具列表{{id=0,num=0},...}
--		s_workType			业务类型
--		s_reason			描述
-- 返回：n					状态码
--		s 					描述
--		s 					发送失败的道具表
this.add_items = function(n_uin, t_items, s_workType, s_reason)
	local s_prefix = mis_config.t_accountAddr.t_gm[n_uin % #mis_config.t_accountAddr.t_gm + 1]
	local s_cmd = 'items_add'
	local s_items = mis_common.table_to_json(t_items)
	local n_ts = ngx.time()
	local s_sign = ngx.md5(s_cmd .. s_items .. s_reason .. n_ts .. n_uin .. '522e6ccde68f4584a3282ce0b0eca1cf')
	local s_url = s_prefix .. 'cmd=' .. s_cmd .. '&items=' .. s_items .. '&reason=' .. s_reason ..
		'&ts=' .. n_ts .. '&uin=' .. n_uin .. '&sign=' .. s_sign

	local s_reason
	repeat
		local n_code, s_desc = http_request('add_items', s_url, 'GET')
		s_reason = s_desc
		if n_code ~= t_retCode.n_OK then
			break
		end
		local t_ret = mis_common.json_to_table(s_desc)
		if t_ret.return_code == 'SUCCESS' then
			-- 统计部分失败
			local t_again
			for n_, s_ in pairs(t_ret.return_result) do
				if s_ ~= 'OK' then
					if not t_again then t_again = {} end
					t_again[#t_again+1] = t_items[n_]
				end
			end
			if t_again then
				s_items = mis_common.table_to_json(t_again)
				break
			end
		else
			-- 全量失败
			mis_log.error('add items failed, ' .. (string_match(s_desc, 'return_msg":"(.*)"') or '') .. ', ' .. s_url)
			break
		end
		return t_retCode.n_OK
	until true

	-- 补发
	local n_code = mis_saveAss.add_job(n_uin, s_workType, s_items)
	if n_code ~= t_retCode.n_OK then
		return n_code, 'add items failed', s_items, (s_reason or "nil")
	end
	return t_retCode.n_OK
end

--------------------------------------------------------------
-- 说明：通知福利服礼包购买行为
-- 参数：n_uin 				迷你号
--		n_giftId			礼包Id
-- 返回：n					状态码
--		ts 					描述
this.notify_ma_buy_gift = function(n_uin, n_giftId)
	local n_ts = ngx.time()
	local s_auth = ngx.md5(n_ts .. '#miniw_907#' .. n_uin)
	local s_url = mis_config.s_maAddr .. 'cmd=set_task_data&user_action=gift_buy&uin=' .. n_uin .. '&time=' .. n_ts ..
		'&auth=' .. s_auth .. '&gift_id=' .. n_giftId
	local n_code, s_desc = http_request('notify_ma_buy_gift', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		return n_code, s_desc
	end
	return t_retCode.n_OK
end

--------------------------------------------------------------
-- 说明：发送邮件
-- 参数：n_uin				目的号
--		s_title				标题
-- 		s_body				正文
--		n_last				留存时间
--		t_attach = {		附件
--			{id = 0, num = 0}
--			...
--		}
--		n_jumpTo			跳转
-- 返回：n					状态码
--		s 					描述
this.send_email = function(n_uin, s_title, s_body, n_last, t_attach, n_jumpTo)
	local s_url = mis_config.t_mail.s_addr .. 'cmd=send_mail_to_player&uin=' .. n_uin .. '&title=' .. s_title ..
		'&body=' .. s_body .. '&end_time=' .. (ngx.time()+n_last)
	if t_attach then
		s_url = s_url .. '&attach='
		for n_, t_ in pairs(t_attach) do
			if n_ == 1 then
				s_url = s_url .. t_.id .. ':' .. t_.num
			else
				s_url = s_url .. ',' .. t_.id .. ':' .. t_.num
			end
		end
	end
	if n_jumpTo then
		s_url = s_url .. '&jump_to=' .. n_jumpTo
	end
	local n_code, s_desc = http_request('send_mail', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		return n_code, s_desc
	elseif string_match(s_desc, 'result%p+(%d+)') ~= '0' then
		s_desc = 'send mail failed, ' .. s_desc
		mis_log.error(s_desc)
		return t_retCode.n_SYS_ERR, s_desc
	end
	return t_retCode.n_OK, s_desc
end

--------------------------------------------------------------
-- 说明：发送系统邮件
-- 参数：
--		s_title				标题
-- 		s_body				正文
-- 		s_cond				条件限定(json格式)
--		n_last				留存时间
--		t_attach = {		附件
--			{id = 0, num = 0}
--			...
--		}
--		n_jumpTo			跳转
-- 返回：n					状态码
--		s 					描述
this.send_sys_email = function(s_title, s_body, s_cond, n_last, t_attach, n_jumpTo)
	local s_attach = ""
	if t_attach then
		for n_, t_ in pairs(t_attach) do
			if n_ == 1 then
				s_attach = s_attach .. t_.id .. ':' .. t_.num
			else
				s_attach = s_attach .. ',' .. t_.id .. ':' .. t_.num
			end
		end
	end

	local t_params = {
		unique_id = "",
		attach = s_attach,
		body = s_body or "",
		cmd = "send_mail",
		cond = s_cond or "",
		end_time = n_last and (ngx.time() + n_last) or "",
		jump_to = n_jumpTo or "",
		title = s_title or "",
	}

	local s_params = mis_uu.getStringBySortKey2(t_params)
	local md5_seed = s_params .. "bf6b8fe2915936c55f3b405ec6ef1389"

	local s_url = mis_config.t_mail.s_addr .. s_params .. "&auth=" .. ngx.md5(md5_seed)
	local n_code, s_desc = http_request('send_sys_mail', s_url, 'GET')

	mis_log.day("weekend_gift_mail", mis_uu.to_str(s_url) .. "  | " .. mis_uu.to_str(s_desc))

	if n_code ~= t_retCode.n_OK then
		return n_code, s_desc
	elseif string_match(s_desc, 'result%p+(%d+)') ~= '0' then
		s_desc = 'send mail failed, ' .. s_desc
		mis_log.error(s_desc)
		return t_retCode.n_SYS_ERR, s_desc
	end
	return t_retCode.n_OK, s_desc
end

--------------------------------------------------------------
-- 说明：好友绑定关系处理
-- 参数：n_uin				目的号
-- 		n_val				绑定标记
-- 返回：n					状态码
--		s 					描述
this.friend_bind_notify = function(n_uin, n_val)
	local s_urlSuffix = 'act=set_activity_flag&flag=0&uin=' .. n_uin .. '&val=' .. n_val
	local s_md5 = ngx.md5(s_urlSuffix .. '924dfb1038cf4dd996776a51008ab8ab')
	local s_url = mis_config.t_friendAddr[n_uin%#mis_config.t_friendAddr+1] .. s_urlSuffix .. '&auth=' .. s_md5
	local n_code, s_desc = http_request('friend_bind_notify', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		return n_code, s_desc
	elseif string_match(s_desc, 'result%p+(%d+)') ~= '0' then
		s_desc = 'friend_bind_notify failed, ' .. (string_match(s_desc, 'msg%p+(%a+)') or '')
		mis_log.error(s_desc)
		return t_retCode.n_SYS_ERR, s_desc
	end
	return t_retCode.n_OK, s_desc
end


this.force_make_friend = function (dst_uin, src_uin)
	dst_uin = tonumber(dst_uin)
	src_uin = src_uin or ngx.ctx.m_params.uin
	if not dst_uin then
		return t_retCode.n_PARAM_ERR
	end
	local s_urlSuffix = 'act=force_make_friend' .. '&des_uin=' .. dst_uin .. '&src_uin=' .. src_uin
	local s_md5 = ngx.md5(s_urlSuffix .. '924dfb1038cf4dd996776a51008ab8ab')
	local s_url = mis_config.t_friendAddr[src_uin%#mis_config.t_friendAddr+1] .. s_urlSuffix .. '&auth=' .. s_md5
	local n_code, s_desc = http_request('force_make_friend', s_url, 'GET')
	
	if n_code ~= t_retCode.n_OK then
		return n_code, s_desc
	elseif string_match(s_desc, 'result%p+(%d+)') ~= '0' then
		s_desc = 'force_make_friend failed, ' .. (string_match(s_desc, 'msg%p+(%a+)') or '')
		mis_log.error(mis_uu.to_str({message = s_desc, code = n_code, desc = s_desc}))
		return t_retCode.n_SYS_ERR, s_desc
	end
	return t_retCode.n_OK, s_desc
end

--------------------------------------------------------------
-- 说明：获取好友列表
-- 参数：n_uin				目的号
-- 		n_val				绑定标记
-- 返回：n					状态码
--		s 					描述
this.query_friend_list = function(n_uin)
	local s_urlSuffix = 'act=query_friend_list&uin=' .. n_uin
	local s_md5 = ngx.md5(s_urlSuffix .. '924dfb1038cf4dd996776a51008ab8ab')
	local s_url = mis_config.t_friendAddr[n_uin%#mis_config.t_friendAddr+1] .. s_urlSuffix .. '&auth=' .. s_md5
	local n_code, ts_desc = http_request('query_friend_list', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		return n_code, ts_desc
	end
	ts_desc = mis_common.json_to_table(ts_desc)
	if ts_desc.result == 0 and ts_desc.friend_list then
		return n_code, ts_desc.friend_list
	else
		mis_log.error('query_friend_list failed, ' .. (ts_desc.return_msg or '') .. ', ' .. s_url)
		return t_retCode.n_SYS_ERR, 'query_friend_list failed'
	end
end

--------------------------------------------------------------
-- 说明：获取关注列表
-- 参数：n_uin				目的号
-- 		n_val				绑定标记
-- 返回：n					状态码
--		s 					描述
this.query_attention_list = function(n_uin)
	local t_params = ngx.ctx.t_params
	local t_query = {
		act = "get_user_attention_list",
		uin = assert(n_uin),
		ver = t_params.ver,
		lang = t_params.lang,
		apiid = t_params.apiid,
		country = t_params.country,
	}

	local s_queryStr = mis_uu.getStringBySortKey2(t_query)
	local s_md5 = ngx.md5(s_queryStr .. "924dfb1038cf4dd996776a51008ab8ab")

	local s_url = mis_config.t_friendAddr[n_uin%#mis_config.t_friendAddr+1] .. s_queryStr .. '&auth=' .. s_md5
	local n_code, ts_desc = http_request('query_attention_list', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		return n_code, ts_desc
	end
	ts_desc = mis_common.json_to_table(ts_desc)
	if ts_desc and ts_desc.result == 0 and ts_desc.attention_list then
		return n_code, ts_desc.attention_list
	else
		mis_log.error('query_attention_list failed, ' .. mis_uu.to_str(ts_desc) .. ', ' .. s_url)
		return t_retCode.n_SYS_ERR, 'query_attention_list failed'
	end
end

--------------------------------------------------------------
-- 说明：查询账号的皮肤
-- 参数：n_uin				目的号
-- 返回：s					皮肤
this.query_owned_skin_account = function(n_uin)	
	local function private_query_path( uin_, path_, url_ )
		local params = {
			cmd      = "query",
			path     = path_,
			uin      = uin_,
			ts       = os.time(),
			ignore   = 1,
		};

		local url_str_ = "";	
		for k, v in pairs(params) do
			url_str_ = url_str_ .. k .. '=' .. v .. '&';
		end

		local md5_seed_ = mis_uu.getStringBySortKey( params ) .. '522e6ccde68f4584a3282ce0b0eca1cf'
		local url_all_ = url_ .. url_str_ .. 'sign=' .. ngx.md5( md5_seed_ );

		local n_code, s_desc = http_request('query_owned_skin_account', url_all_, 'GET')
		if n_code ~= t_retCode.n_OK then
			mis_log.error('query_owned_skin_account failed1, ' .. s_desc .. ', ' .. url_all_)
			return {}
		end
		local t_desc = mis_common.json_to_table(s_desc)
		if t_desc.return_code == 'SUCCESS' then
			return t_desc.return_result or {};
		else
			mis_log.error('query_owned_skin_account failed2, ' .. s_desc .. ', ' .. url_all_)
			return {}
		end
	end

	local s_gm = mis_config.t_accountAddr.t_gm[n_uin % #mis_config.t_accountAddr.t_gm + 1]
	local ct_ret_ = private_query_path(n_uin, 'Account.BillDataSvr', s_gm)
	local skin_list = {}
	if  type(ct_ret_)=='table' and type(ct_ret_["Account.BillDataSvr"]) == 'table' then
        if  ct_ret_["Account.BillDataSvr"].RoleSkinInfo and type(ct_ret_["Account.BillDataSvr"].RoleSkinInfo) == 'table'then
			skin_list = ct_ret_["Account.BillDataSvr"].RoleSkinInfo
        end
	end
	ct_ret_ = private_query_path(n_uin, "leveldb.RoleSkinInfo" , s_gm)
	if  type(ct_ret_)=='table' and type(ct_ret_["leveldb.RoleSkinInfo"]) == 'table' then

		local leveldb_skin_list = ct_ret_["leveldb.RoleSkinInfo"]
		for k,v in pairs(leveldb_skin_list) do
			table_insert(skin_list,v)
		end
	end

	return skin_list
end 

--查询用户注册信息与充值
this.query_owned_creat_recharge = function(n_uin, recharge_flag)
	local function private_query_path( uin_, path_, url_ )
		local params = {
			cmd      = "query",
			path     = path_,
			uin      = uin_,
			ts       = os.time(),
			ignore   = 1,
		};

		local url_str_ = "";	
		for k, v in pairs(params) do
			url_str_ = url_str_ .. k .. '=' .. v .. '&';
		end

		local md5_seed_ = mis_uu.getStringBySortKey( params ) .. '522e6ccde68f4584a3282ce0b0eca1cf'
		local url_all_ = url_ .. url_str_ .. 'sign=' .. ngx.md5( md5_seed_ );

		local n_code, s_desc = http_request('query_owned_creat_recharge', url_all_, 'GET')
		if n_code ~= t_retCode.n_OK then
			mis_log.error('query_owned_creat_recharge failed1, ' .. s_desc .. ', ' .. url_all_)
			return {}
		end
		local t_desc = mis_common.json_to_table(s_desc)
		if t_desc.return_code == 'SUCCESS' then
			return t_desc.return_result or {};
		else
			mis_log.error('query_owned_creat_recharge failed2, ' .. s_desc .. ', ' .. url_all_)
			return {}
		end
	end

	local s_gm = mis_config.t_accountAddr.t_gm[n_uin % #mis_config.t_accountAddr.t_gm + 1]
	
	local ct_ret_ = private_query_path(n_uin, 'Account.AccountCreateTime', s_gm)
	
	if recharge_flag == nil then
		ct_ret_['leveldb.recharge'] = private_query_path(n_uin, 'leveldb.recharge', s_gm)['leveldb.recharge']
	end
	

	return ct_ret_

end

--------------------------------------------------------------
-- 说明：查询账号的avatar
-- 参数：uin				目的号
-- 返回：s					皮肤
this.query_owned_avatar_account = function(uin)
	-- local url = ''
	-- if #mis_config.t_accountAddr.query_avatar_url == 1 then
	-- 	url = mis_config.t_accountAddr.query_avatar_url[1]
	-- else
	-- 	local index = math.random( 1, #mis_config.t_accountAddr.query_avatar_url )
	-- 	url = mis_config.t_accountAddr.query_avatar_url[index]
	-- end
	-- url = url .. 'uin=' .. uin .. '&reqfield=ModelID,ExpireTime'
	-- local headers_ = { ["Connection"]="Keep-Alive",["User-Agent"]="PostmanRuntime/7.26.5",}
	-- local ret, body = ns_network.getHttpPage( url ,headers_);
	-- if  ret == 200 then
	-- 	local avatar = uu.json2table( body )
	-- 	if avatar and avatar.code == 0  then
	-- 		return avatar.msg
	-- 	end
	-- end
	return {}
end

--------------------------------------------------------------
-- 说明：获取所有道具
-- 参数：n_item_ids		    		使用礼包道具生成的itemid
-- 参数：n_item_counts		    	使用礼包道具生成的itemnum
-- 返回：t_items					返回的道具 
this.get_props_by_switch  = function(n_item_ids, n_item_counts)
	local t_items = {}								
	local t_item_ids = n_item_ids or {}					
	local t_item_counts = n_item_counts or {}

	if #t_item_ids == #t_item_counts then 
		for i = 1, #t_item_ids do
			table_insert(t_items, {id = t_item_ids[i], num = t_item_counts[i]}) 
		end 
	end 

	return t_items
end 

--------------------------------------------------------------
-- 说明：使用道具
-- 参数：n_skin_info				玩家皮肤数据
-- 参数：n_times					使用次数 
-- 参数：n_item_ids		    		使用礼包道具生成的itemid
-- 参数：n_item_counts		    	使用礼包道具生成的itemnum
-- 参数：n_item_probs		    	使用礼包道具生成的概率
-- 参数：n_item_tags	    		使用礼包道具生成的tag类型
-- 返回：t_items					返回的道具 
this.use_prop  = function(n_skin_info,n_avatar_info, n_times, n_item_ids, n_item_counts, n_item_probs, n_item_tags, n_item_skins)
	-- 计算是否拥有永久皮肤
	local function is_exist_skin(skin_id_)
		for k, v  in pairs(n_skin_info) do
			if v.ExpireTime == -1 and v.SkinID == skin_id_ then
				return true
			end
		end
		-- for k, v in pairs(n_avatar_info) do
		-- 	--if v.ExpireTime == - 1 and v.ModelID ==
		-- end
		return false 
	end 

	-- 根据权重随机产生普通道具
	local function rand_normal_id_by_probs(exist_skin_, item_tags_, item_props_, item_skins_, total_prop_)
		local n_rand = math_random(1,  math_floor(total_prop_ * 10000)) * 0.0001
		local n_add = 0
		for i = 1, #item_props_ do
			if exist_skin_[i] == false and tonumber(item_tags_[i]) ~= mis_config.t_giftTagType.n_DETERMINE_TAG and tonumber(item_skins_[i])  == 0 then
				if tonumber(item_props_[i]) + n_add >= n_rand then 
					return i
				else
					n_add = n_add + tonumber(item_props_[i])
				end 	
			end
		end  
		return -1
	end 

	-- 根据权重随机产生道具
	local function rand_id_by_probs(exist_skin_, item_tags_, item_props_, item_skins_, total_prop_)
		local n_rand = math_random(1,  math_floor(total_prop_ * 10000)) * 0.0001
		local n_add = 0
		for i = 1, #item_props_ do
			if exist_skin_[i] == false and tonumber(item_tags_[i]) ~= mis_config.t_giftTagType.n_DETERMINE_TAG then 
				if tonumber(item_props_[i]) + n_add >= n_rand then 
					return i
				else
					n_add = n_add + tonumber(item_props_[i])
				end 	
			end
		end  
		return -1
	end 

	local t_items = {}								--  最后产生的道具
	local t_id2num = {}								--  id映射数量 
	local t_item_ids = n_item_ids or {}					
	local t_item_counts = n_item_counts or {}
	local t_item_probs = n_item_probs or {}
	local t_item_tags = n_item_tags or {}
	local t_item_skins = n_item_skins or {}
	local n_item_count = #n_item_ids
	local b_exist_skin = {}

	if n_item_count == #t_item_counts 
		and n_item_count == #t_item_probs 
		and n_item_count == #t_item_tags 
		and n_item_count == #t_item_skins
		then 
		
		-- 是否已经拥有永久皮肤
		for i = 1, n_item_count do
			b_exist_skin[i] = (tonumber(t_item_skins[i]) ~= 0 and is_exist_skin(tonumber(t_item_skins[i])))
		end 

		-- 必得道具
		for i = 1, n_item_count do
			if b_exist_skin[i] == false and tonumber(t_item_tags[i]) == mis_config.t_giftTagType.n_DETERMINE_TAG then 
				local n_id = tonumber(t_item_ids[i])
				t_id2num[n_id] = tonumber(t_item_counts[i]) * n_times
			end 
		end 	

		-- 随机道具总共概率(永久皮肤剔除)
		local n_total = 0
		-- 随机道具总共概率(剔除特殊道具)
		local n_total_noraml = 0

		for i = 1, n_item_count do
			if b_exist_skin[i] == false and tonumber(t_item_tags[i]) ~= mis_config.t_giftTagType.n_DETERMINE_TAG then
				n_total = n_total +  tonumber(t_item_probs[i])
			end  
			if b_exist_skin[i] == false and tonumber(t_item_tags[i]) ~= mis_config.t_giftTagType.n_DETERMINE_TAG and tonumber(t_item_skins[i]) == 0 then
				n_total_noraml = n_total_noraml +  tonumber(t_item_probs[i])
			end 
		end 

		-- 随机道具
		if n_times <= 10 then 
			for j = 1, n_times do 
				local i = rand_id_by_probs(b_exist_skin, t_item_tags, t_item_probs, t_item_skins, n_total)	
				if i ~= -1 then 
					local n_id = tonumber(t_item_ids[i])
					t_id2num[n_id] = t_id2num[n_id] or 0
					t_id2num[n_id] = t_id2num[n_id] + tonumber(t_item_counts[i])
				end 
			end 
		else 
			local n_use_times = 0				-- 已经使用的次数
			local n_rand_times = n_times - 10   -- 用来随机的次数,留10次随机
			-- 直接按比例分 
			for i = 1, n_item_count do
				if b_exist_skin[i] == false and tonumber(t_item_tags[i]) ~= mis_config.t_giftTagType.n_DETERMINE_TAG then 
					local n_num = math_floor(n_rand_times * tonumber(t_item_probs[i]) /n_total) 
					-- 固定皮肤只给一个 
					if tonumber(t_item_skins[i]) ~= 0 and n_num > 1 then 
						 n_num = 1 
					end 
					if n_num >= 1 then 
						local n_id = tonumber(t_item_ids[i])
						t_id2num[n_id] = t_id2num[n_id] or 0
						t_id2num[n_id] = t_id2num[n_id] + n_num * tonumber(t_item_counts[i])
						n_use_times = n_use_times + math_floor(n_rand_times * tonumber(t_item_probs[i]) /n_total ) 
					end  
				end 
			end 

			-- 剩余10次随机给
			if n_use_times < n_times then
				for j = 1, n_times - n_use_times do 	
					local i = rand_normal_id_by_probs(b_exist_skin, t_item_tags, t_item_probs, t_item_skins, n_total_noraml)	
					if i ~= -1 then 
						local n_id = tonumber(t_item_ids[i])
						t_id2num[n_id] = t_id2num[n_id] or 0
						t_id2num[n_id] = t_id2num[n_id] + tonumber(t_item_counts[i])
					end 
				end 
			end 
		end 
	end 

	for k, v in pairs(t_id2num) do
		if v > 0 then 
			table_insert(t_items, {id = k, num = v})
		end 
	end 
				
	-- mis_log.debug('use_prop' ..n_item_count..#t_item_probs..#t_item_tags..#t_item_skins..mis_common.table_to_string(t_items))

	return t_items
end 

--------------------------------------------------------------
---scr_uin_  = 来源玩家（发起好友申请）
---des_uin_  = 目标玩家
---relation_ = 关系编号      2=单向好友   3=双向好友
---返回值:  成功{result=0}   失败{result=21}
this.friend_has_relation = function(n_scr_uin, n_des_uin, n_relation)
	-- mis_log.debug( "call friend_has_relation" );
	local params = {
		act      = "has_relation",
		src_uin  = n_scr_uin,
		des_uin  = n_des_uin,
		relation = n_relation,
	};

	local url_str = "";	
	for k, v in pairs(params) do
		url_str = url_str .. k .. '=' .. v .. '&';
	end

	local md5_seed = mis_uu.getStringBySortKey2(params) .. '924dfb1038cf4dd996776a51008ab8ab'
	local s_url = mis_config.t_friendAddr[n_scr_uin%#mis_config.t_friendAddr+1] .. url_str.. 'auth='..ngx.md5(md5_seed)

	local n_code, s_desc = http_request('friend_has_relation', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		mis_log.error('friend_has_relation failed1, ' .. s_desc .. ', ' .. s_url)
		return n_code, s_desc
	elseif string_match(s_desc, 'result%p+(%d+)') ~= '0' then
		return t_retCode.n_SYS_ERR, s_desc
	end
	
	return t_retCode.n_OK, s_desc
end

--------------------------------------------------------------
-- 申请好友接口
---scr_uin_  = 来源玩家（发起好友申请）
---des_uin_  = 目标玩家
---from =  来源， 0:游戏中  1:来自应用盒子  2:来自web前端  3:组队
---返回值:  成功{result=0}   失败{result=21}
this.apply_friend = function(n_scr_uin, n_des_uin, from)

	-- mis_log.debug( "call friend_has_relation" );
	local params = {
		act      = "apply_friend",
		src_uin  = n_scr_uin,
		des_uin  = n_des_uin,
		from = from or 0,
	};

	local url_str = "";	
	for k, v in pairs(params) do
		url_str = url_str .. k .. '=' .. v .. '&';
	end

	local md5_seed = mis_uu.getStringBySortKey2(params) .. '924dfb1038cf4dd996776a51008ab8ab'
	local s_url = mis_config.t_friendAddr[n_scr_uin%#mis_config.t_friendAddr+1] .. url_str.. 'auth='..ngx.md5(md5_seed)

	local n_code, s_desc = http_request('friend_has_relation', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		mis_log.error('friend_has_relation failed1, ' .. s_desc .. ', ' .. s_url)
		return n_code, s_desc
	elseif string_match(s_desc, 'result%p+(%d+)') ~= '0' then
		return t_retCode.n_SYS_ERR, s_desc
	end
	
	return t_retCode.n_OK, s_desc
end

--------------------------------------------------------------
-- 说明：导流消息推送
-- 参数：n_scr_uin			发起用户
-- 参数：s_uin_list			推送用户
-- 参数：s_msg               推送消息
-- 返回值:  成功{result=0}   非零失败
this.push_diversion_message = function(n_scr_uin, s_des_uin, s_msg)
	local extend_data = {
		nickname = '迷你队长',
		shareType = 0,
		src_user_version = 2, -- 发送方版本
		des_user_version = 1  -- 接收方版本
	}
	local params = {
		cmd      = "multi_send_chat_msg",
		src_uin  = n_scr_uin,
		des_uin  = s_des_uin,
		msgtype	 = 1,							-- 1.普通消息 2.分享消息 3.邀请进房消息
		pushchannel = 1,						--0：走以前的接口, 不变，消息发往账户服--1：走新推送通道，消息发往新的推送服务 --2: 两个通道都推送
		msg      = s_msg,
		extend_data = ngx.encode_base64(mis_common.table_to_json(extend_data))
	};

	--mis_log.day('diversion', 's_des_uin:' .. s_des_uin .. '|push_diversion_message|' .. params.extend_data)

	local url_str = "";
	for k, v in pairs(params) do
		url_str = url_str .. k .. '=' .. ngx.escape_uri(v) .. '&';
	end

	local md5_seed = mis_uu.getStringBySortKey2(params) .. '924dfb1038cf4dd996776a51008ab8ab'
	local s_url = mis_config.t_friendAddr[n_scr_uin%#mis_config.t_friendAddr+1] .. url_str.. 'auth='..ngx.md5(md5_seed)

	local n_code, s_desc = http_request('push_diversion_message', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		mis_log.error('friend_has_relation failed1, ' .. s_desc .. ', ' .. s_url)
		return n_code, s_desc
	end

	return t_retCode.n_OK, s_desc
end

--------------------------------------------------------------
-- 说明：map 获取联机大厅—综合列表
-- 返回值:  成功{result=0}   非零失败
this.query_map_list = function()
	local n_now = ngx.time()
	local t_params = {
		cmd      	= "get_map_list",
		uin      	= 1000,
		game_label 	= 1,
		time 		= n_now,
		requestid 	= ngx.md5(n_now)
	};

	local url_str = "";
	for k, v in pairs(t_params) do
		url_str = url_str .. k .. '=' .. v .. '&';
	end

	local s_md5_seed = 'cmd=get_map_list&game_label=1&time=' .. t_params.time .. '&uin=' .. t_params.uin  .. 'f5711eb1640712de051e5aedc35329c3'
	local s_url = mis_config.s_map_url .. url_str.. 'auth=' .. ngx.md5(s_md5_seed)

	local n_code, st_desc = http_request('query_map_list', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		mis_log.error('query_map_list failed1, ' .. st_desc .. ', ' .. s_url)
		return n_code, st_desc
	end

	return t_retCode.n_OK, mis_common.json_to_table(st_desc or '')
end

--------------------------------------------------------------
-- 说明：profile 获取用户版本
-- 返回值:  成功{result=0}   非零失败
this.query_profile_info = function(n_scr_uin, s_des_uin)
	local t_params = {
		act  = "getProfileBatch2",
		uin  = n_scr_uin,
		op_uin_list  = s_des_uin,
		time = ngx.time(),
		json = 1
	};

	local url_str = "";
	for k, v in pairs(t_params) do
		url_str = url_str .. k .. '=' .. v .. '&';
	end

	local md5_seed 	= t_params.time .. '#_php_miniw_2016_#' .. t_params.uin
	local s_url 	= mis_config.s_profile_url .. url_str.. 'auth='..ngx.md5(md5_seed)

	local n_code, st_desc = http_request('query_profile_info', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		mis_log.error('query_profile_info failed1, ' .. st_desc .. ', ' .. s_url)
		return n_code, st_desc
	end

	return t_retCode.n_OK, mis_common.json_to_table(st_desc or '')
end

--------------------------------------------------------------
-- 说明：profile 设置用户版本
-- 返回值:  成功{result=0}   非零失败
this.set_profile_info = function(n_scr_uin, n_ver)
	local t_params = {
		cmd  = "setProfileUserVersion",
		uin  = n_scr_uin,
		client_version  = n_ver or 1,
		time = ngx.time(),
		json = 1
	};

	local url_str = "";
	for k, v in pairs(t_params) do
		url_str = url_str .. k .. '=' .. v .. '&';
	end

	local md5_seed 	= t_params.uin .. '#LY1006#' .. t_params.time .. '#' .. t_params.cmd .. '#'
	local s_url 	= mis_config.s_profile_url .. url_str.. 'token='..ngx.md5(md5_seed)

	local n_code, st_desc = http_request('query_profile_info', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		mis_log.error('query_profile_info failed1, ' .. st_desc .. ', ' .. s_url)
		return n_code, st_desc
	end

	return t_retCode.n_OK, mis_common.json_to_table(st_desc or '')
end

--------------------------------------------------------------
-- 说明：查询账号的avatar
-- 参数：uin				目的号
-- 返回：s					皮肤
this.query_user_avatar = function(uin)
	 local url = ''
	 if mis_config.t_accountAddr == nil or mis_config.t_accountAddr.query_avatar_url == nil then
	 	return {}
	 end

	 if #mis_config.t_accountAddr.query_avatar_url == 1 then
	 	url = mis_config.t_accountAddr.query_avatar_url[1]
	 else
	 	math.randomseed( ngx.now() )
	 	local index = math.random( 1, #mis_config.t_accountAddr.query_avatar_url )
	 	url = mis_config.t_accountAddr.query_avatar_url[index]
	 end
	 url = url .. 'uin=' .. uin .. '&reqfield=ModelID,ExpireTime'
	 local headers_ = { ["Connection"]="Keep-Alive",["User-Agent"]="PostmanRuntime/7.26.5",}
	 local ret, body = ns_network.getHttpPage( url ,headers_);
	 if  ret == 200 then
	 	local avatar = mis_uu.json2table( body )
	 	if avatar and avatar.code == 0  then
	 		return avatar.msg
	 	end
	 end
	return {}
end

-- 说明：服务器上报战年兽事件
-- 返回值:  成功{result=0}   非零失败
this.notify_mission_event = function(s_act, n_uin, s_type)
	local t_params = {
		cmd  = s_act,
		uin  = n_uin,
		event  = 32,
		value = 1,
		mission_type = s_type,
		time = ngx.time()
	};

	local url_str = "";
	for k, v in pairs(t_params) do
		url_str = url_str .. k .. '=' .. v .. '&';
	end

	local md5_seed 	= t_params.time .. '#miniw_907#' .. t_params.uin
	local s_url 	= mis_config.s_mission_url .. url_str.. 'auth='..ngx.md5(md5_seed)

	local n_code, st_desc = http_request('notify_mission_event', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		mis_log.error('notify_mission_event failed1, ' .. st_desc .. ', ' .. s_url)
		return n_code, st_desc
	end

	return t_retCode.n_OK, st_desc
end

-- modpush推送
-- @param sendTime	推送时间戳（单位：毫秒），指定在此时间推送消息
-- @param scheme	跳转链接（deeplink）
this.modpush_send = function(uin, s_type, mergePushId, sendTime, scheme, country, lang)
	local t_params = {
		uin = uin,
		pushType = s_type,
		region = country or ngx.ctx.t_params.country,
		language = lang or ngx.ctx.t_params.lang,
		pushTime = sendTime,
		scheme = scheme,
		mergePushId = mergePushId,
		timestamp = math_floor(ngx.now() * 1000)
	};

	local md5_seed = mis_uu.getStringBySortKey2(t_params) .. "&" .. mis_config.s_mobpush_single_key
	local sign = ngx.md5(md5_seed)

	local s_url 	= mis_config.s_mobpush_single_send_url
	local t_header  = {["Content-Type"] = "application/json", ["Authorization"] = sign}

	local n_code, st_desc = http_request('modpush_send', s_url, 'POST', t_header, mis_uu.table2json(t_params))
	if n_code ~= t_retCode.n_OK then
		mis_log.day("modpush_error", 'modpush_send failed1, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return n_code, st_desc
	end

	local t_resp = mis_uu.json2table(st_desc)
	if type(t_resp.meta) ~= "table" then
		mis_log.day("modpush_error", 'modpush_send failed2, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return t_retCode.n_SYS_ERR, "mobpush send error"
	end

	if t_resp.meta.code ~= 0 then
		if t_resp.meta.code ~= 1023 then
			mis_log.day("modpush_error", 'modpush_send failed3, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		end
		return t_retCode.n_SYS_ERR, "mobpush send error"
	end

	return t_retCode.n_OK, t_resp
end

-- modpush撤销推送
this.modpush_cancel = function(uin, batchId, mergePushId)
	local t_params = {
		batchId = batchId,
		mergePushId = mergePushId,
		timestamp = math_floor(ngx.now() * 1000)
	};

	local md5_seed = mis_uu.getStringBySortKey2(t_params) .. "&" .. mis_config.s_mobpush_single_key
	local sign = ngx.md5(md5_seed)

	local s_url 	= mis_config.s_mobpush_single_cancel_url
	local t_header  = {["Content-Type"] = "application/json", ["Authorization"] = sign}

	local n_code, st_desc = http_request('modpush_cancel', s_url, 'POST', t_header, mis_uu.table2json(t_params))
	if n_code ~= t_retCode.n_OK then
		mis_log.day("modpush_error", 'modpush_cancel failed1, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return n_code, st_desc
	end

	local t_resp = mis_uu.json2table(st_desc)
	if type(t_resp.meta) ~= "table" then
		mis_log.day("modpush_error", 'modpush_cancel failed2, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return t_retCode.n_SYS_ERR, "mobpush cancel error"
	end

	if t_resp.meta.code ~= 0 then
		mis_log.day("modpush_error", 'modpush_cancel failed3, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return t_retCode.n_SYS_ERR, "mobpush cancel error"
	end

	return t_retCode.n_OK, t_resp
end

-- modpush推送
-- @param sendTime	推送时间戳（必须大于当前时间至少5分钟，单位：毫秒），指定在此时间推送消息
this.modpush_send_batch = function(s_type, sendTime)
	local t_params = {
		pushType = s_type,
		region = "CN",
		language = "0",
		sendTime = sendTime,
		timestamp = math_floor(ngx.now() * 1000),
		sign = nil,
	};

	local md5_seed = "pushType=" .. t_params.pushType
		.. "&language=" .. t_params.language
		.. "&region=" .. t_params.region 
		.. "&sendTime=" .. t_params.sendTime
		.. "&timestamp=" .. t_params.timestamp 
		.. "&secretKey=ofpcmsopgxelzbpxqbczhx4ug9c939xu"
	t_params.sign = ngx.md5(md5_seed)

	local s_url 	= mis_config.s_mobpush_push_url
	local t_header  = {["Content-Type"] = "application/json"}

	local n_code, st_desc = http_request('modpush_send_batch', s_url, 'POST', t_header, mis_uu.table2json(t_params))
	if n_code ~= t_retCode.n_OK then
		mis_log.day("modpush_error", 'modpush_send_batch failed1, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return n_code, st_desc
	end

	local t_resp = mis_uu.json2table(st_desc)
	if type(t_resp.meta) ~= "table" then
		mis_log.day("modpush_error", 'modpush_send_batch failed2, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return t_retCode.n_SYS_ERR, "mobpush send error"
	end

	if t_resp.meta.code ~= 0 then
		mis_log.day("modpush_error", 'modpush_send_batch failed3, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return t_retCode.n_SYS_ERR, "mobpush send error"
	end

	return t_retCode.n_OK, t_resp
end

-- modpush注册
this.modpush_register = function(n_uin, s_type)
	local t_params = {
		pushType = s_type,
		uin = n_uin,
		timestamp = math_floor(ngx.now() * 1000),
		sign = nil,
	};

	local md5_seed = "pushType=" .. t_params.pushType
		.. "&uin=" .. t_params.uin
		.. "&timestamp=" .. t_params.timestamp 
		.. "&tpye=add&secretKey=ofpcmsopgxelzbpxqbczhx4ug9c939xu"
	t_params.sign = ngx.md5(md5_seed)

	local s_url 	= mis_config.s_mobpush_add_url
	local t_header  = {["Content-Type"] = "application/json"}

	local n_code, st_desc = http_request('modpush_register', s_url, 'POST', t_header, mis_uu.table2json(t_params))
	if n_code ~= t_retCode.n_OK then
		mis_log.day("modpush_error", 'modpush_register failed1, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return n_code, st_desc
	end

	local t_resp = mis_uu.json2table(st_desc)
	if type(t_resp.meta) ~= "table" then
		mis_log.day("modpush_error", 'modpush_register failed2, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return t_retCode.n_SYS_ERR, "register push error"
	end

	if t_resp.meta.code ~= 0 then
		mis_log.day("modpush_error", 'modpush_register failed3, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return t_retCode.n_SYS_ERR, "register push error"
	end

	return t_retCode.n_OK, t_resp
end

-- modpush反注册
this.modpush_unregister = function(n_uin, s_type)
	local t_params = {
		pushType = s_type,
		uin = n_uin,
		timestamp = math_floor(ngx.now() * 1000),
		sign = nil,
	};

	local md5_seed = "pushType=" .. t_params.pushType
		.. "&uin=" .. t_params.uin
		.. "&timestamp=" .. t_params.timestamp 
		.. "&tpye=del&secretKey=ofpcmsopgxelzbpxqbczhx4ug9c939xu"
	t_params.sign = ngx.md5(md5_seed)

	local s_url 	= mis_config.s_mobpush_del_url
	local t_header  = {["Content-Type"] = "application/json"}

	local n_code, st_desc = http_request('modpush_unregister', s_url, 'POST', t_header, mis_uu.table2json(t_params))
	if n_code ~= t_retCode.n_OK then
		mis_log.day("modpush_error", 'modpush_unregister failed1, ' .. st_desc .. ', ' .. s_url)
		return n_code, st_desc
	end
	
	local t_resp = mis_uu.json2table(st_desc)
	if type(t_resp.meta) ~= "table" then
		mis_log.day("modpush_error", 'modpush_unregister failed2, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return t_retCode.n_SYS_ERR, "unregister push error"
	end

	if t_resp.meta.code ~= 0 then
		mis_log.day("modpush_error", 'modpush_unregister failed3, ' .. st_desc .. ', ' .. mis_uu.to_str(t_params))
		return t_retCode.n_SYS_ERR, "unregister push error"
	end

	return t_retCode.n_OK, t_resp
end

local cloud_rank_request = function (router, data, header)
    local uri  = mis_config.t_rank_server.s_url .. router
	local body = mis_uu.table2json(data)
    local request = {
		appid = mis_config.t_rank_server.s_appid,
		md5      = ngx.md5(body),
        signType = 'md5',
        ts       = ngx.time(),
		appkey = mis_config.t_rank_server.s_appkey,
	}
    request.sign = ngx.md5( mis_uu.getStringBySortKey2( request ))
	request.appkey = nil
    header = header or {
        ["Content-Type"] = "application/json",
        ["Connection"]   = "Keep-Alive",
        ["User-Agent"]   = "mnw",
		--["User-Agent"]   = "apifox/1.0.0 (https://www.apifox.cn)",
    }
	
    local result = mis_uu.json2table(http_post(uri, request, body, header) or '')
    if mis_uu.tableIsEmpty(result) or result.code ~= 0 then
        return false
    end

    return true, result.data
end

this.get_cloud_national_user_rank = function (map_id, t_name, uin)
    local succ, result = cloud_rank_request('/api/v2/rank/getRankByUin',{
			uin = tonumber(uin),
			order = tonumber(0),				--0降序 1升序
			aid = map_id,				--
			rankName = t_name,
		}
	)

    if not succ or not result then
        return false, {}
    end

    return true, result
end

this.get_cloud_national_rank = function (map_id, t_name)
    local succ, result = cloud_rank_request('/api/v2/rank/getRankInArea',{
			indexEnd = tonumber(100),			--排行榜范围结束
			filterCondition = tonumber(1),		--1大于等于
			filterNum = tonumber(0),			--默认为0不筛选	
			order = tonumber(0),				--0降序 1升序
			indexStart = tonumber(1),			--范围开始
			aid = map_id,				--
			rankName = t_name,
		}
	)

    if not succ or not result then
        return false
    end

    return true, result.ret
end

this.set_cloud_national_score = function (map_id, t_name, data)
    local succ, result = cloud_rank_request('/api/v2/rank/addRankData',{
			rankDatas = data,
			aid = map_id,				--
			rankName = t_name,
		}
	)

    if not succ or not result then
        return false, {}
    end

    return true, result
end

this.clear_cloud_national_rank = function (map_id, t_name)
    local succ, result = cloud_rank_request('/api/v2/rank/clearRank',{
			aid = map_id,				--
			rankName = t_name,
		}
	)

    if not succ or not result then
        return false, {}
    end

    return true, result
end

local cloud_server_request = function (router, data, header)
    local uri  = mis_config.t_cloud_server.s_url .. router
    local body = mis_uu.table2json(data)
    local request = {
        invoker  = mis_config.t_cloud_server.s_invoker,
        key      = mis_config.t_cloud_server.s_key,
        signType = 'md5',
        md5      = ngx.md5(body),
        ts       = ngx.time(),
    }
    request.sign = ngx.md5( mis_uu.getStringBySortKey2( request ))
    header = header or {
        ["Content-Type"] = "application/json",
        ["Connection"]   = "Keep-Alive",
        ["User-Agent"]   = "mnw",
    }

    local result = mis_uu.json2table(http_post(uri, request, body, header) or '')
    if mis_uu.tableIsEmpty(result) or result.code ~= 0 then
        return false
    end

    return true, result.data
end

-- !@ namespace : 该游戏某个数据集名称，e.g. ds_2_100000:global
-- !@ id        : 地图ID, e.g. 800000
-- !@ key       : 普通数据存储Key, e.g. testInt1
-- !@ value     : 设置key对应的值, e.g. 100501
this.set_cloud_dhs_data = function (id, namespace, key, value)
    return cloud_server_request( '/api/v1/dhs/setValue',{
			namespace = namespace,
			aid       = tostring(id),
			key       = tostring(key),
			value     = value,
		}
	) and true or false
end

this.get_cloud_dhs_data = function (id, namespace, key)
    local succ, result = cloud_server_request('/api/v1/dhs/getValue',{
			namespace = namespace .. ':global',
			aid       = tostring(id),
			key       = tostring(key),
		}
	)
    if not succ then
        return false
    end

    return true, result.value
end


--查询手机绑定
this.query_bind_phone = function(n_uin)
	local function private_query_path( uin_, path_, url_ )
		local params = {
			cmd      = "query",
			path     = path_,
			uin      = uin_,
			ts       = os.time(),
			ignore   = 1,
		};

		local url_str_ = "";	
		for k, v in pairs(params) do
			url_str_ = url_str_ .. k .. '=' .. v .. '&';
		end

		local md5_seed_ = mis_uu.getStringBySortKey( params ) .. '522e6ccde68f4584a3282ce0b0eca1cf'
		local url_all_ = url_ .. url_str_ .. 'sign=' .. ngx.md5( md5_seed_ );

		local n_code, s_desc = http_request('query_bind_phone', url_all_, 'GET')
		if n_code ~= t_retCode.n_OK then
			mis_log.error('query_bind_phone failed1, ' .. s_desc .. ', ' .. url_all_)
			return {}
		end
		local t_desc = mis_common.json_to_table(s_desc)
		if t_desc.return_code == 'SUCCESS' then
			return t_desc.return_result or {};
		else
			mis_log.error('query_bind_phone failed2, ' .. s_desc .. ', ' .. url_all_)
			return {}
		end
	end

	local s_gm = mis_config.t_accountAddr.t_gm[n_uin % #mis_config.t_accountAddr.t_gm + 1]

	local ct_ret_ = private_query_path(n_uin, 'Account.Phone', s_gm)
	if ct_ret_ and type(ct_ret_["Account.Phone"])=="string" and #ct_ret_["Account.Phone"] == 11 then
		return true
	end

	return false
end


local function call_business_server(url_, params_)
	mis_log.debug( "call_business_server url=" .. url_ )
	local url_str_ = ""
	params_.time = params_.time or mis_uu.now()
	for k, v in pairs(params_) do
		url_str_ = url_str_ .. k .. '=' .. ngx.escape_uri(v) .. '&'
	end

	local n_uin = ngx.ctx.m_params.uin
	local n_ts = params_.time
	local s_md5 = ngx.md5(n_ts .. '#miniw_907#' .. n_uin)
	local url_all_ = url_ .. url_str_
	url_all_ = url_all_ .. 'auth=' .. s_md5
	local headers_ = { ["Connection"]="Keep-Alive",["User-Agent"]="PostmanRuntime/7.26.5",}
	local ret, body = ns_network.getHttpPage( url_all_, headers_ )
	if  ret == 200 then
		return mis_uu.safe_loadstring( body )
	else
		return {}
	end
end

--------------------------------------------------------------
-- 说明：查询玩家是否可以购买VIP
-- 参数：uin				目的号
-- 参数：op_uin				被查询对象
-- 参数: store_id           购买ID
---------------------------------------------------------------
this.query_user_vip_condition = function(uin, op_uin, store_id)
	local server = mis_config.t_business_url
	if not server then
		return {}
	end
	local param_ = {
		cmd = 'gm_check_buy_vip',
		uin = uin,
		op_uin = op_uin,
		store_id = store_id,
	}

   return call_business_server(server, param_)
end

--------------------------------------------------------------
-- 说明：购买VIP
-- 参数：uin				目的号
-- 参数：uin_lst			被查询对象
-- 参数: store_id           购买ID
---------------------------------------------------------------
this.vip_batchbuy_req = function(uin, uin_lst, store_id, discount)
	local server = mis_config.t_business_url
	if not server then
		return {}
	end

	local param_ = {
		cmd = 'gm_batch_buy_vip',
		uin = uin,
		uin_lst = uin_lst,
		store_id = store_id,
		discount  = discount,
	}

   return call_business_server(server, param_)
end

-- 查询迷你大会员
this.query_mini_vip = function (uin)
	uin = uin or ngx.ctx.m_params.uin
	local url = mis_config.t_business_url
	if not url then
		return false
	end
	local time_ = mis_uu.now()
	local md5 = ngx.md5(time_ .. "#miniw_907#" .. uin) --in
	local Url = string.format("%suin=%s&time=%s&cmd=%s&auth=%s&json=1&op_uin=%s",url,uin,time_,'gm_get_vip_state_data', md5,uin)

	local n_code, s_desc = http_request('query_mini_vip', Url, 'GET')
	if n_code ~= t_retCode.n_OK then
		mis_log.error('query_mini_vip failed1, ' .. s_desc .. ', ' .. Url)
		return false
	end
	local t_desc = mis_common.json_to_table(s_desc)
	if t_desc and tonumber(t_desc.ret) == 0 then
		if (tonumber(t_desc.data.end_date) or 0) < time_ then
			return true, false
		else
			return true, true
		end
		return true, t_desc.return_result or {};
	else
		mis_log.error('query_mini_vip failed2, ' .. s_desc .. ', ' .. Url)
		return false
	end
end


--------------------------------------------------------------
-- 说明：购买VIP
-- 参数：uin				目的号
-- friend_uin			    好友迷你号
-- 参数: store_id           购买ID
this.vip_friendbuy_req =  function(uin, friend_uin, store_id)
	local server = mis_config.t_business_url
	if not server then
		return false
	end
	local param_ = {
		cmd = 'gm_vip_friend_buy',
		uin = uin,
		friend_uin = friend_uin,
		store_id = store_id,
	}

   return call_business_server(server, param_)
end

--------------------------------------------------------------
-- 查询好友令
---n_uin  		= 玩家uin
---s_src_name  	= 玩家昵称
---返回值:  成功{result=0}   失败{result=21}
this.query_friend_token = function(n_uin, s_src_name)

	local params = {
		act      	= "query_ftoken",
		uin  		= n_uin,
		src_name  	= s_src_name
	}

	local url_str = ""
	for k, v in pairs(params) do
		url_str = url_str .. k .. '=' .. v .. '&'
	end

	local md5_seed = mis_uu.getStringBySortKey2(params) .. '924dfb1038cf4dd996776a51008ab8ab'
	local s_url = mis_config.t_friendAddr[n_uin%#mis_config.t_friendAddr+1] .. url_str.. 'auth='..ngx.md5(md5_seed)
	
	local n_code, s_desc = http_request('query_friend_token', s_url, 'GET')
	if n_code ~= t_retCode.n_OK then
		mis_log.error('query_friend_token failed1, ' .. s_desc .. ', ' .. s_url)
		return n_code, s_desc
	elseif string_match(s_desc, 'result%p+(%d+)') ~= '0' then
		return t_retCode.n_SYS_ERR, s_desc
	end
	
	return t_retCode.n_OK, mis_common.json_to_table(s_desc)
end

return this
